package com.wzcl.app.config.oauth.authentication.mobile;


import com.wzcl.app.config.oauth.model.UserDetailsImpl;
import com.wzcl.app.config.oauth.service.MyUserDetailsServiceImpl;
import com.wzcl.app.dao.model.AppUser;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.dto.UserDto;
import com.wzcl.app.service.UserService;
import com.wzcl.app.service.impl.UserServiceImpl;
import com.wzcl.app.utils.SpringUtil;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;

@Log4j2
@Data
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {

    private MyUserDetailsServiceImpl myUserDetailsService;

    private UserDetailsChecker preAuthenticationChecks = new DefaultPreAuthenticationChecks();


    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //这个authentication就是SmsCodeAuthenticationToken
        SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication;

        String phone = (String)authenticationToken.getPrincipal();
        //校验手机号
        UserDetails user = myUserDetailsService.loadUserByPhone(phone);
        if (user == null) {
            UserService userService = (UserServiceImpl) SpringUtil.getBean("userServiceImpl");
            UserDto userDto = new UserDto();
            userDto.setPhone(phone);
            userDto.setPassword(phone);
            AppUser appUser = userService.registerUser(userDto);
            if(appUser == null){
                throw new BusinessException(CodeMsg.SYSTEM_ERR);
            }
            user = new UserDetailsImpl(appUser);
        }
        preAuthenticationChecks.check(user);
        //这时候已经认证成功了
        SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user, user.getAuthorities());
        authenticationResult.setDetails(authenticationToken.getDetails());

        return authenticationResult;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        //该SmsCodeAuthenticationProvider智支持SmsCodeAuthenticationToken的token认证
        return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }

    private class DefaultPreAuthenticationChecks implements UserDetailsChecker {
        public void check(UserDetails user) {
            if (!user.isAccountNonLocked()) {
                log.debug("User account is locked");
                throw new LockedException("User account is locked");
            }

            if (!user.isEnabled()) {
                log.debug("User account is disabled");
                throw new DisabledException("User is disabled");
            }

            if (!user.isAccountNonExpired()) {
                log.debug("User account is expired");
                throw new AccountExpiredException("User account has expired");
            }
        }
    }

}
